package com.wsz.user.consumer;

import com.alibaba.fastjson.JSONObject;
import com.wsz.pojo.*;
import com.wsz.pojo.dto.MatchingDto;
import com.wsz.user.fengin.BotFeginClient;
import com.wsz.user.fengin.MatchingFeginClient;
import com.wsz.user.mapper.BotMapper;
import com.wsz.user.mapper.RecordMapper;
import com.wsz.user.utils.Game;
import com.wsz.user.mapper.UserInfoMapper;
import com.wsz.utils.TokenUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/websocket/{token}")  // 注意不要以'/'结尾
public class WebSocketServer {

    public static final ConcurrentHashMap<String,WebSocketServer> users = new ConcurrentHashMap<>();//存储当前所有用户的websocket 线程安全

    private UserInfo user;//当前websocket 用户

    public static RecordMapper recordMapper;

    public static UserInfoMapper userInfoMapper;
    private static BotMapper botMapper;

    private Session session = null;//每个连接使用session维护

    public Game game = null;

    private static MatchingFeginClient matchingFeginClient;

    public static BotFeginClient botFeginClient;

    @Autowired
    public void setBotFeginClient(BotFeginClient botFeginClient){
        WebSocketServer.botFeginClient = botFeginClient;
    }

    @Autowired
    public void setMatchingFeginClient(MatchingFeginClient matchingFeginClient){
        WebSocketServer.matchingFeginClient = matchingFeginClient;
    }

    @Autowired
    public void setBotMapper(BotMapper botMapper){
        WebSocketServer.botMapper = botMapper;
    }

    @Autowired
    public void setRecordMapper(RecordMapper recordMapper){
        WebSocketServer.recordMapper = recordMapper;
    }

    @Autowired
    public void setUserMapper(UserInfoMapper userInfoMapper){
        WebSocketServer.userInfoMapper = userInfoMapper;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        // 建立连接
        this.session = session;
        try{
            String userId = TokenUtils.getUserId(token);
            this.user = userInfoMapper.selectById(userId);

            if(this.user != null) users.put(userId,this);
            else this.session.close();

        }catch (Exception e){
            throw new RuntimeException("token 不合法！！！");
        }
    }

    @OnClose
    public void onClose() {
        // 关闭链接
        if(this.user != null){
            users.remove(user.getId());
        }

    }

    @OnMessage
    public void onMessage(String message, Session session) {
        // 从Client接收消息
        JSONObject data = JSONObject.parseObject(message);

        String event = data.getString("event");
        if("start".equals(event)){
            startMatching(data.getString("bot_id"));
        }else if("stop".equals(event)){
            stopMatching();
        }else if("move".equals(event)){
            move(data.getInteger("direction"));
        }


    }

    public static void startGame(String aId,String bId,String a_bot_id,String b_bot_id){
        UserInfo a = userInfoMapper.selectById(aId);
        UserInfo b = userInfoMapper.selectById(bId);

        Bot botA = null;
        Bot botB = null;

        if(!a_bot_id.equals("-1")) {
            botA = botMapper.selectById(a_bot_id);
        }

        if(!b_bot_id.equals("-1")) {
            botB = botMapper.selectById(b_bot_id);
        }

        Game game = new Game(13,14,20,a.getId(),b.getId(),botA,botB);
        game.createMap();
        if(users.get(a.getId()) != null){
            users.get(a.getId()).game = game;
        }
        if(users.get(b.getId()) != null){
            users.get(b.getId()).game = game;
        }

        game.start();

        JSONObject respGame = new JSONObject();
        respGame.put("a_info",game.getPlayerA());
        respGame.put("b_info",game.getPlayerB());


        JSONObject respA = new JSONObject();
        respA.put("event","start-matching");
        respA.put("username",b.getUsername());
        respA.put("avatar",b.getPhoto());
        respA.put("gamemap",game.getG());
        respA.put("respGame",respGame);
        if( users.get(a.getId()) != null){
            users.get(a.getId()).sendMessage(respA.toJSONString());
        }


        JSONObject respB = new JSONObject();
        respB.put("event","start-matching");
        respB.put("username",a.getUsername());
        respB.put("avatar",a.getPhoto());
        respB.put("gamemap",game.getG());
        respB.put("respGame",respGame);
        if(users.get(b.getId()) != null) {
            users.get(b.getId()).sendMessage(respB.toJSONString());
        }

    }

    private void move(Integer d){
        if(game.getPlayerA().getId().equals(user.getId())){
            if(game.getPlayerA().getBot_id().equals("-1"))
            game.setNextStepA(d);
        }else if(game.getPlayerB().getId().equals(user.getId())){
            if(game.getPlayerB().getBot_id().equals("-1"))
            game.setNextStepB(d);
        }
    }

    private void startMatching(String bot_id){
        MatchingDto matchingDto = new MatchingDto();
        matchingDto.setUserId(this.user.getId());
        matchingDto.setRanting(this.user.getRanting());
        matchingDto.setBot_id(bot_id);
        R r = matchingFeginClient.addPlayer(matchingDto);
    }


    private void stopMatching(){
        MatchingDto matchingDto = new MatchingDto();
        matchingDto.setUserId(this.user.getId());
        matchingDto.setRanting(this.user.getRanting());
        R r = matchingFeginClient.removePlayer(matchingDto);

    }

    public void sendMessage(String message) {
        synchronized (this.session){
            try{
                this.session.getBasicRemote().sendText(message);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
}